package com.conversationboard.controller;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.conversationboard.database.BatchQueries;
import com.conversationboard.database.Database;
import com.conversationboard.logger.LogMessageType;
import com.conversationboard.logger.Logger;
import com.conversationboard.model.User;
import com.conversationboard.site.Site;

@WebServlet(name = "AdminInitialiseMessageCountsControllerServlet", urlPatterns = "/Admin/AdminInitialiseMessageCountsControllerServlet")
public class AdminInitialiseMessageCountsControllerServlet extends HttpServlet {

	private static final long serialVersionUID = 4901194654573997331L;

	private class LatestMessageId {

		private int boardId;
		private int threadId;
		private int count;


		public int getBoardId() {
			return boardId;
		}


		public void setBoardId(int boardId) {
			this.boardId = boardId;
		}


		public int getThreadId() {
			return threadId;
		}


		public void setThreadId(int threadId) {
			this.threadId = threadId;
		}


		public int getCount() {
			return count;
		}


		public void setCount(int count) {
			this.count = count;
		}

	}


	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		try {
			request.setCharacterEncoding("UTF-8");
			response.setCharacterEncoding("UTF-8");

			User user = User.get(request.getUserPrincipal().getName());

			if (!user.isSiteAdmin()) {
				return;
			}

			if (!request.getParameter("key").equals(request.getSession().getId())) {
				return;
			}

			if (!Site.isShut()) {
				Logger.log(new Date(), "Can only initialise latest message IDs when site is shut", user, LogMessageType.SYSTEM);
				return;
			}

			/* Count all the messages in all the threads */

			Connection connection = null;

			List<LatestMessageId> latestMessageIDs = new LinkedList<LatestMessageId>();

			try {

				Logger.log(new Date(), "Starting initialisation of latest message IDs", user);

				connection = Database.getConnection();

				PreparedStatement statement = connection.prepareStatement(BatchQueries.MAX_MESSAGEID_PER_THREAD);
				statement.execute();

				ResultSet resultSet = statement.getResultSet();

				while (resultSet.next()) {

					int boardId = resultSet.getInt("boardid");
					int threadId = resultSet.getInt("threadid");
					int latestMessageId = resultSet.getInt("latestmessageid");

					LatestMessageId mc = new LatestMessageId();
					mc.setBoardId(boardId);
					mc.setThreadId(threadId);
					mc.setCount(latestMessageId);

					latestMessageIDs.add(mc);
				}

				statement.close();

				Logger.log(new Date(), "Got all latest message IDs... Going to update", user);

				/* Batch up a thousand at a time and update the threads table */

				/*
				 * Note: modified this query to only update threads that have a
				 * latestmessageid of zero
				 */

				statement = connection.prepareStatement(BatchQueries.UPDATE_BROKEN_LATEST_MESSAGE_IDS);
				int counter = 0;
				int total = 0;

				for (LatestMessageId latestMessageId : latestMessageIDs) {

					statement.setInt(1, latestMessageId.getCount());
					statement.setInt(2, latestMessageId.getBoardId());
					statement.setInt(3, latestMessageId.getThreadId());
					statement.addBatch();

					counter++;
					if ((counter % 1000) == 0) {
						int[] updateCounts = statement.executeBatch();

						for (int i : updateCounts) {
							total += i;
						}
					}
				}

				int[] updateCounts = statement.executeBatch();

				for (int i : updateCounts) {
					total += i;
				}

				Logger.log(new Date(), "Completed update of all latest message IDs. Updated: " + total + " threads.", user);

			} finally {
				Database.close(connection);
			}

		} catch (SQLException e) {
			throw new ServletException(e);
		}
	}
}